package level.editor.control.collision;

import java.awt.AWTException;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;

import javax.swing.SwingUtilities;

import level.editor.control.layer.LayerBuffer;
import level.editor.control.layer.LayerPainter;
import level.editor.control.main.Main;
import level.editor.control.tile.TileConstants;
import level.model.Collision;

public class CollisionBuffer extends LayerBuffer
{
	public CollisionBuffer(Integer zOrder, Point point, Main main,
			boolean isRect)
	{
		super(zOrder, main);
		initialPoint = point;
		endPoint = point;
		this.isRect = isRect;
		if (!isRect)
			snapMouse(initialPoint);
	}

	public void setEndPoint(Point point)
	{
		endPoint = point;
	}

	public void finish(CollisionLayer layer)
	{

		if (!isRect)
		{
			snapMouse(endPoint);

			if (!endPoint.equals(initialPoint))
			{
				Collision collision = new Collision();
				collision.setLine(new Line2D.Float(initialPoint, endPoint));
				layer.addObject(collision);
			}
		}

		else if (isRect)
		{
			Point newEnd = new Point();
			Point newBegin = new Point();

			newEnd.x = endPoint.x
					+ (initialPoint.x > endPoint.x ? 0
							: TileConstants.TILE_SIZE);
			newEnd.y = endPoint.y
					+ (initialPoint.y > endPoint.y ? 0
							: TileConstants.TILE_SIZE);

			newBegin.x = initialPoint.x
					+ (initialPoint.x <= endPoint.x ? 0
							: TileConstants.TILE_SIZE);
			newBegin.y = initialPoint.y
					+ (initialPoint.y <= endPoint.y ? 0
							: TileConstants.TILE_SIZE);

			Rectangle2D rect = new Line2D.Float(newBegin, newEnd).getBounds2D();

			Collision collision = new Collision();
			collision.setLine(new Line2D.Float(new Point((int) rect.getMinX(),
					(int) rect.getMinY()), new Point((int) rect.getMaxX(),
					(int) rect.getMinY())));
			layer.addObject(collision);

			collision = new Collision();
			collision.setLine(new Line2D.Float(new Point((int) rect.getMinX(),
					(int) rect.getMinY()), new Point((int) rect.getMinX(),
					(int) rect.getMaxY())));
			layer.addObject(collision);

			collision = new Collision();
			collision.setLine(new Line2D.Float(new Point((int) rect.getMaxX(),
					(int) rect.getMaxY()), new Point((int) rect.getMaxX(),
					(int) rect.getMinY())));
			layer.addObject(collision);

			collision = new Collision();
			collision.setLine(new Line2D.Float(new Point((int) rect.getMaxX(),
					(int) rect.getMaxY()), new Point((int) rect.getMinX(),
					(int) rect.getMaxY())));
			layer.addObject(collision);
		}

		main.setDirty(Main.DIRTY);
		main.createMemento();
		main.remove(this);
	}

	@Override
	public void paintComponent(Graphics gOld)
	{
		setSize(getParent().getSize());

		Graphics2D g = (Graphics2D) gOld;

		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);

		g.setStroke(new BasicStroke(3f));
		g.setColor(Color.YELLOW);

		int originX = (int) main.getOrigin().getX();
		int originY = (int) main.getOrigin().getY();

		Point initial = new Point((int) (originX + initialPoint.getX()),
				(int) (originY + initialPoint.getY()));
		Point end = new Point((int) (originX + endPoint.getX()),
				(int) (originY + endPoint.getY()));

		if (!isRect)
		{
			Line2D line = new Line2D.Float(initial, end);
			Ellipse2D ellipse = new Ellipse2D.Float(initial.x
					- LayerPainter.DOT_OFFSET, initial.y
					- LayerPainter.DOT_OFFSET, LayerPainter.SIZE,
					LayerPainter.SIZE);
			g.fill(ellipse);

			ellipse = new Ellipse2D.Float(end.x - LayerPainter.DOT_OFFSET,
					end.y - LayerPainter.DOT_OFFSET, LayerPainter.SIZE,
					LayerPainter.SIZE);
			g.fill(ellipse);

			g.draw(line);
		}

		else if (isRect)
		{
			Point newEnd = new Point();
			Point newBegin = new Point();

			newEnd.x = endPoint.x
					+ (initialPoint.x > endPoint.x ? 0
							: TileConstants.TILE_SIZE);
			newEnd.y = endPoint.y
					+ (initialPoint.y > endPoint.y ? 0
							: TileConstants.TILE_SIZE);

			newBegin.x = initialPoint.x
					+ (initialPoint.x <= endPoint.x ? 0
							: TileConstants.TILE_SIZE);
			newBegin.y = initialPoint.y
					+ (initialPoint.y <= endPoint.y ? 0
							: TileConstants.TILE_SIZE);

			initial = new Point((int) (originX + newBegin.getX()),
					(int) (originY + newBegin.getY()));
			end = new Point((int) (originX + newEnd.getX()),
					(int) (originY + newEnd.getY()));

			Line2D line = new Line2D.Float(initial, end);
			Rectangle2D rect = line.getBounds2D();

			Ellipse2D ellipse = new Ellipse2D.Float((int) rect.getX()
					- LayerPainter.DOT_OFFSET, (int) rect.getY()
					- LayerPainter.DOT_OFFSET, LayerPainter.SIZE,
					LayerPainter.SIZE);
			g.fill(ellipse);

			ellipse = new Ellipse2D.Float((int) (rect.getX() + rect.getWidth())
					- LayerPainter.DOT_OFFSET, (int) rect.getY()
					- LayerPainter.DOT_OFFSET, LayerPainter.SIZE,
					LayerPainter.SIZE);
			g.fill(ellipse);

			ellipse = new Ellipse2D.Float((int) rect.getX()
					- LayerPainter.DOT_OFFSET,
					(int) (rect.getY() + rect.getHeight())
							- LayerPainter.DOT_OFFSET, LayerPainter.SIZE,
					LayerPainter.SIZE);
			g.fill(ellipse);

			ellipse = new Ellipse2D.Float((int) (rect.getX() + rect.getWidth())
					- LayerPainter.DOT_OFFSET,
					(int) (rect.getY() + rect.getHeight())
							- LayerPainter.DOT_OFFSET, LayerPainter.SIZE,
					LayerPainter.SIZE);
			g.fill(ellipse);

			g.draw(rect);
		}
	}

	private void snapMouse(Point point)
	{
		int originX = (int) main.getOrigin().getX();
		int originY = (int) main.getOrigin().getY();

		Point snap = new Point((int) (originX + point.getX()),
				(int) (originY + point.getY()));
		SwingUtilities.convertPointToScreen(snap, this);
		try
		{
			new Robot().mouseMove((int) snap.getX(), (int) snap.getY());
		}
		catch (AWTException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private Point initialPoint;
	private Point endPoint;
	private boolean isRect;
}
